package services

import (
	"booking-service/internal/models"
	"booking-service/internal/storage"
	"errors"
	"log"
	"time"
)

type BookingService struct {
	orderStorage            storage.OrderStorage
	roomAvailabilityStorage storage.RoomAvailabilityStorage
}

func NewBookingService(orderStorage storage.OrderStorage, roomAvailabilityStorage storage.RoomAvailabilityStorage) *BookingService {
	return &BookingService{
		orderStorage:            orderStorage,
		roomAvailabilityStorage: roomAvailabilityStorage,
	}
}

func (s *BookingService) CreateOrder(order models.Order) error {
	days := daysBetween(order.From, order.To)
	for _, day := range days {
		availability, err := s.roomAvailabilityStorage.GetAvailability(order.HotelID, order.RoomID, day)
		if err != nil || availability.Quota < 1 {
			return errors.New("room not available for selected dates")
		}
	}

	for _, day := range days {
		err := s.roomAvailabilityStorage.UpdateAvailability(order.HotelID, order.RoomID, day, -1)
		if err != nil {
			return err
		}
	}

	err := s.orderStorage.CreateOrder(order)
	if err != nil {
		return err
	}

	log.Printf("Order created successfully: %+v", order)
	return nil
}

func daysBetween(from, to time.Time) []time.Time {
	if from.After(to) {
		return nil
	}

	days := make([]time.Time, 0)
	for d := toDay(from); !d.After(toDay(to)); d = d.AddDate(0, 0, 1) {
		days = append(days, d)
	}

	return days
}

func toDay(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
}
